package org.viettan.android.main.managers;

import java.util.List;

import org.viettan.android.main.io.EntityRetrievalException;
import org.viettan.android.main.io.NetworkException;
import org.viettan.android.main.io.NetworkUtility;
import org.viettan.android.main.io.UrlUtility;
import org.viettan.android.main.model.Article;
import org.viettan.android.main.model.Campaign;
import org.viettan.android.main.model.InfoSection;
import org.viettan.android.main.model.Section;
import org.viettan.android.main.resources.ResourcesManager;
import org.viettan.android.main.xml.ArticleXmlParser;

import android.net.Uri;
import android.util.Pair;

import com.google.inject.Inject;
import com.google.inject.Singleton;

/**
 * Singleton to manage retrieving the articles from the Viet Tan website feed.
 */
@Singleton
public class ArticleManager extends BaseEntityManager<Article> {

    @Inject
    private ResourcesManager resourcesUtility;

    private final UrlUtility urlUtility;
    private final NetworkUtility networkUtility;

    @Inject
    ArticleManager(UrlUtility urlUtility, NetworkUtility networkUtility, ArticleXmlParser xmlParser) {
	super(networkUtility, xmlParser);
	this.urlUtility = urlUtility;
	this.networkUtility = networkUtility;
    }

    /**
     * Returns the list of recently-uploaded {@link Article}s in reverse-chronological order.
     *
     * @param useCache
     *            retrieve the data from the cache if it is there
     * @return List of {@link Article}s recently uploaded
     * @throws EntityRetrievalException
     */
    public List<Article> getLatestNews(boolean useCache) throws EntityRetrievalException {
	return getEntities(urlUtility.getLatestFeed(), useCache);
    }

    /**
     * Returns the list of {@link Article}s in a {@link Section}.
     *
     * @param sectionId
     *            the ID of the section to retrieve articles from
     * @param useCache
     *            retrieve the data from the cache if it is there
     * @return List of {@link Article}s in the section
     * @throws EntityRetrievalException
     */
    public List<Article> getArticlesInSection(int sectionId, boolean useCache)
	    throws EntityRetrievalException {
	return getEntities(urlUtility.getSectionArticlesFeed(sectionId), useCache);
    }

    /**
     * Returns the full {@code Article} downloaded at the given url.
     *
     * @param useCache
     *            retrieve the data from the cache if it is there
     * @param articleXmlUrl
     *            URL to the XML representation of the article
     * @return fully-populated {@code Article}
     * @throws EntityRetrievalException
     */
    public Article getArticle(Uri articleXmlUrl, boolean useCache) throws EntityRetrievalException {
	return getEntity(articleXmlUrl, useCache);
    }

    /**
     * Returns all the main and related {@code Article} of the given campaign.
     *
     * @param campaignId
     *            id of the {@link Campaign}
     * @param useCache
     *            retrieve the data from the cache if it is there
     * @return A {@link Pair} of main and related {@code Article}. The main articles are really just
     *         pointers to sections.
     * @throws EntityRetrievalException
     */
    public Pair<List<Article>, List<Article>> getCampaignArticles(int campaignId, boolean useCache)
	    throws EntityRetrievalException {
	String rawXml;
	try {
	    rawXml = networkUtility
		    .httpGet(urlUtility.getSectionArticlesFeed(campaignId), useCache);
	    List<Article> mainArticles = getEntities(rawXml, "mainarticles");
	    List<Article> relatedArticles = getEntities(rawXml, "relatedarticles");
	    return Pair.create(mainArticles, relatedArticles);
	} catch (NetworkException e) {
	    throw new EntityRetrievalException(e);
	}
    }

    /**
     * Returns a hardcoded/local {@code Article} for the info section.
     *
     * @param infoSection
     *            the info section to display
     * @return {@code Article} that only has title, body and imageId populated.
     */
    public Article getArticle(InfoSection infoSection) {
	return new Article().setTitle(resourcesUtility.getString(infoSection.getTitleResourceId()))
		.setBody(resourcesUtility.getString(infoSection.getBodyResourceId()));
    }
}